﻿using System.Collections;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Text;

namespace DimensionsHelper.LanguageService.Syntax;

public class QualifiedName : SyntaxNode, IReadOnlyList<Identifier>
{
    /// <summary>
    ///     默认的空限定名
    /// </summary>
    public static readonly QualifiedName Default = new(Identifier.Default, null);


    private readonly SyntaxList<Identifier> _identifierParts;

    internal QualifiedName(Identifier name, SyntaxNode? parent) :
        base(SyntaxKinds.QualifiedName, parent)
    {
        _identifierParts = new SyntaxList<Identifier>();

        if (!Identifier.IsDefaultOrEmpty(name))
        {
            AddChildMemberToReadOnlyField(_identifierParts, name);
        }
    }


    public override bool IsEmpty => _identifierParts.IsEmpty;

    public int Count => _identifierParts.Count;

    public Identifier this[int index] => _identifierParts[index];

    public IEnumerator<Identifier> GetEnumerator()
    {
        return _identifierParts.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }


    public static bool IsDefault(QualifiedName name)
    {
        return ReferenceEquals(name, Default) || name.IsEmpty;
    }


    /// <summary>
    ///     添加一个成员限定名
    /// </summary>
    public void AddMemberName(Identifier name)
    {
        AddChildMemberToReadOnlyField(_identifierParts, name);
    }


    /// <summary>
    ///     获取完全限定名列表
    /// </summary>
    public ImmutableArray<Identifier> GetFullNameArray()
    {
        return [.._identifierParts];
    }


    /// <summary>
    ///     获取全限定名，中间使用'.'分隔
    /// </summary>
    /// <returns></returns>
    public string GetFullName()
    {
        if (_identifierParts.Count == 0)
        {
            return string.Empty;
        }

        return string.Join('.', _identifierParts.Select(id => id.Text));
    }


    /// <summary>
    ///     获取到指定命名为止的全名，包含指定名称，如果指定节点不在当前列表中，返回结果
    ///     和<see cref="GetFullName" />相同
    /// </summary>
    public string GetFullNameUntil(Identifier name)
    {
        if (_identifierParts.IsEmpty)
        {
            return string.Empty;
        }


        StringBuilder nameBuilder = new();

        foreach (Identifier part in _identifierParts)
        {
            if (nameBuilder.Length > 0)
            {
                nameBuilder.Append('.');
            }

            nameBuilder.Append(part.Text);

            if (ReferenceEquals(part, name))
            {
                break;
            }
        }

        return nameBuilder.ToString();
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        AcceptList(visitor, _identifierParts);
    }
}


public static partial class NodeFactory
{
    public static QualifiedName CreateQualifiedName(SyntaxNode? parent, Identifier identifier)
    {
        return new QualifiedName(identifier, parent);
    }


    public static QualifiedName CreateQualifiedName(SyntaxNode? parent,
        IReadOnlyList<Identifier> identifierParts)
    {
        Debug.Assert(identifierParts.Count > 0);
        QualifiedName qualifiedName = new(identifierParts[0], parent);
        for (int i = 1; i < identifierParts.Count; i++)
        {
            qualifiedName.AddMemberName(identifierParts[i]);
        }

        return qualifiedName;
    }
}